BITS 16
%include "system.inc"
org 0x8000
start:
	db 'NT'
	call win_set_up
    call os_get_cpuid
    ret
os_get_cpuid:
%macro print 1+                    ; It's not lazy, it's just good use of NASM's macro features.
    section .data
        %%string db %1, 0
    section .text


    mov si,%%string
    call win_print_string
%endmacro
    mov si,name_string
    call win_print_string
cpuid_get_vendor_string:
    xor eax, eax                ; Get the 12-byte processor vendor string.
    cpuid                    ; This function is present on all CPUID-enabled processors.

    mov [cpuid_vendor_string], ebx        ; Store it in the string buffer.
    mov [cpuid_vendor_string+4], edx
    mov [cpuid_vendor_string+8], ecx

cpuid_get_processor_fms:
    mov eax, 1                ; Get the processor features and CPU signature (family info)
    cpuid
    
    mov [cpuid_processor_features], edx    ; Save the processor feature DWORD - we'll parse this later.

    push eax                ; Get the stepping.
    and eax, 000Fh
    mov [cpuid_processor_stepping], eax
    pop eax
    
    push eax                ; Get the model.
    and eax, 00F0h
    shr eax, 4
    mov [cpuid_processor_model], eax
    pop eax
    
    push eax                ; Get the family.
    and eax, 0F00h
    shr eax, 8
    mov [cpuid_processor_family], eax
    pop eax
    
cpuid_show_info:
    mov si,cpu_string_
    call win_print_string
    mov si, cpuid_vendor_string
    call win_print_string
    call win_new_line
    
    mov eax, 80000000h            ; Request the highest extended CPUID function number.
    cpuid
    
    cmp eax, 80000004h            ; Can we call 80000002h through 80000004h?
    jl .nostring                ; If not, skip this section.
    
    mov di, cpuid_processor_string        ; Throw the destination buffer into DI
    
    mov eax, 80000002h            ; Get the first sixteen bytes of the processor ID string
    cpuid
    stosd                    ; Store EAX
    mov eax, ebx
    stosd                    ; Store EBX
    mov eax, ecx
    stosd                    ; Store ECX
    mov eax, edx
    stosd                    ; Store EDX
    
    mov eax, 80000003h            ; Get the middle sixteen bytes of the processor ID string
    cpuid
    stosd                    ; Store EAX
    mov eax, ebx
    stosd                    ; Store EBX
    mov eax, ecx
    stosd                    ; Store ECX
    mov eax, edx
    stosd                    ; Store EDX
    
    mov eax, 80000004h            ; Get the last sixteen bytes of the processor ID string
    cpuid
    stosd                    ; Store EAX
    mov eax, ebx
    stosd                    ; Store EBX
    mov eax, ecx
    stosd                    ; Store ECX
    mov eax, edx
    stosd                    ; Store EDX
    
    mov si,cp_nme
    call win_print_string
    
    mov ax, cpuid_processor_string        ; Intel seems to have leading spaces to pad the whole
    call os_string_chomp            ; thing out to 48 bytes. This is the case on the i7.
    
    mov si, cpuid_processor_string        ; Finally, output the processor ID string.
    call win_print_string
    call win_new_line
    
    
.nostring:
    mov si,cpu_fam
    call win_print_string
    mov edx, [cpuid_processor_family]    ; high word of EAX should be zeroes anyways.
	mov ax,cpuid_processor_family
	CALL direct_print_dec
    ;call win_print_string
    call win_new_line
    
    print 'model: '
    mov edx, [cpuid_processor_model]    ; high word of EAX should be zeroes anyways.
	mov ax,cpuid_processor_model
	call direct_print_dec
    ;call win_print_string
    call win_new_line
    
    print 'stepping: '
    mov edx, [cpuid_processor_stepping]    ; high word of EAX should be zeroes anyways.
	mov ax,cpuid_processor_stepping
	call direct_print_dec
    ;call win_print_string
    call win_new_line
    
cpuid_show_features:                ; This is where things get boring.
    mov edx, [cpuid_processor_features]    ; Load up the processor features we stored earlier.
    print 'CPU features: '
    
.fpu:
    bt edx, 0
    jnc .vme
    print 'fpu '

.vme:
    bt edx, 1
    jnc .de
    print 'vme '
    
.de:
    bt edx, 2
    jnc .pse
    print 'de '

.pse:
    bt edx, 3
    jnc .tsc
    print 'pse '
    
.tsc:
    bt edx, 4
    jnc .msr
    print 'tsc '
    
.msr:
    bt edx, 5
    jnc .pae
    print 'msr '

.pae:
    bt edx, 6
    jnc .mce
    print 'pae '
    
.mce:
    bt edx, 7
    jnc .cx8
    print 'mce '
    
.cx8:
    bt edx, 8
    jnc .apic
    print 'cx8 '
    
.apic:
    bt edx, 9
    jnc .sep
    print 'apic '
    
.sep:
    bt edx, 11
    jnc .mtrr
    print 'sep '
    
.mtrr:
    bt edx, 12
    jnc .pge
    print 'mtrr '
    
.pge:
    bt edx, 13
    jnc .mca
    print 'pge '
    
.mca:
    bt edx, 14
    jnc .cmov
    print 'mca '
    
.cmov:
    bt edx, 15
    jnc .pat
    print 'cmov '
    
.pat:
    bt edx, 16
    jnc .pse36
    print 'pat '
    
.pse36:
    bt edx, 17
    jnc .pn
    print 'pse36 '
    
.pn:
    bt edx, 18
    jnc .clflush
    print 'pn '
    
.clflush:
    bt edx, 19
    jnc .dts
    print 'clflush '
    
.dts:
    bt edx, 21
    jnc .acpi
    print 'dts '
    
.acpi:
    bt edx, 22
    jnc .mmx
    print 'acpi '
    
.mmx:
    bt edx, 23
    jnc .fxsr
    print 'mmx '
    
.fxsr:
    bt edx, 24
    jnc .sse
    print 'fxsr '
    
.sse:
    bt edx, 25
    jnc .sse2
    print 'sse '
    
.sse2:
    bt edx, 26
    jnc .ss
    print 'sse2 '
    
.ss:
    bt edx, 27
    jnc .ht
    print 'ss '
    
.ht:
    bt edx, 28
    jnc .tm
    print 'ht '
    
.tm:
    bt edx, 29
    jnc .ia64
    print 'tm '
    
.ia64:
    bt edx, 30
    jnc .pbe
    print 'ia64 '
    
.pbe:
    bt edx, 31
    jnc .done
    print 'pbe '
    
    
.done:
   jmp program_end
    
program_end:
    call win_new_line
	mov si,ram_info
    call win_print_string
    xor ax,ax
    int 0x12
   call os_int_to_string
  mov si,ax
   call win_print_string
    mov di,tstring
    call os_long_int_to_string
    mov si,tstring
    call win_print_string
    jmp lolguy
direct_itoa:
	pusha
	push es
	push cs
	pop es

	mov cx, 0
	mov bx, 10			; Set BX 10, for division and mod
	mov di, .t			; Get our pointer ready

.push:
	mov dx, 0
	div bx				; Remainder in DX, quotient in AX
	inc cx                          ; Increase pop loop counter
	push dx				; Push remainder, so as to reverse order when popping
	test ax, ax			; Is quotient zero?
	jnz .push			; If not, loop again
.pop:
	pop dx				; Pop off values in reverse order, and add 48 to make them digits
	add dl, '0'			; And save them in the string, increasing the pointer each time
	mov [es:di], dl
	inc di
	dec cx
	jnz .pop

	mov byte [es:di], 0		; Zero-terminate string

	pop es
	popa
	mov si, .t			; Return location of string
	ret

	.t times 7 db 0
direct_print_dec:
	pusha
.printloop:
	mov ax,dx
	cmp ax,0
	je .zero

	mov ax,dx
	call direct_itoa
	push bx
	mov bx, 0007h
	push ds
	push cs
	pop ds
	call win_print_string
	pop ds
	pop bx

	popa
	ret
.zero:
	mov ah,0Eh
	mov bx,0007h
	mov al,'0'
	int 10h
	popa
	ret
lolguy:
	call mouse_init
	call os_hide_cursor
	jmp quit_wait
quit_wait:
	call mouselib_freemove
	jc .keypress
	call mouselib_anyclick
	jc .check
	jmp quit_wait
.keypress:
	jmp quit_wait
.nokey:
	call os_clear_screen
	int 0x20
.check:
	call mouselib_locate
	cmp cx,67
	je .checky
	jmp quit_wait
.checky:
	cmp dx,2
	je .nokey
    name_string db  'CPUID written by Troy Martin,Ported to POS by Siddharth Gautam',4,5,0
    cpu_string_ db 'CPU Vendor ID : ',0
    cp_nme db 'CPU name: ',0
    cpu_fam db 'CPU Family: ',0
    ram_info db 'RAM: ',0
    cpuid_vendor_string        times 13 db 0
    cpuid_processor_string        times 49 db 0
    cpuid_processor_stepping    dd 0
    cpuid_processor_model        dd 0
    cpuid_processor_family        dd 0
    cpuid_processor_features    dd 0
    tstring: times 50 db 0
	close db '[X]',0
%include "winlib/io/stdiowin.asm"
%include "winlib/mouse/mouse.asm"
; ------------------------------------------------------------------